/**
 * Gcc vector benchmark
 * Julien Etienne, 2008
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <cstdlib>
#include <ctime>
#include <iostream>

#include "vector.h"

#define xstr(x) str(x)
#define str(x)  #x

#ifndef NB_PROFILING_LOOP
	#error NB_PROFILING_LOOP is not defined.
#endif

int main(int argc, char** args){
	clock_t clockStart, clockEnd;

	/* Display build information */
	std::cout << "Gcc vector benchmark: "
	          << "VECTOR_TYPE=" << xstr(VECTOR_TYPE)
			  << " (" << (8*sizeof(VECTOR_TYPE)) << " bits)"
			  << ", VECTOR_SIZE=" << xstr(VECTOR_SIZE)
			  << ", USE_GCC_VECTOR=" << (USE_GCC_VECTOR+0)
			  << std::endl;

	/* Initialize vector values */
	Vector a, b, c, result;
	result[0] = result[1] = result[2] = result[3] = 0;
	a[0] = a[1] = a[2] = a[3] = 0;
	b[0] = 1;
	b[1] = 2;
	b[2] = 3;
	b[3] = 4;

	/* Profile the basic vector operations */
	clockStart = clock();
	for(long i=0; i<NB_PROFILING_LOOP; i++){
		c = a + b;
	}
	clockEnd = clock();

	/* Force code generation by using the result
	 * else optimizer might just remove the previous loop ;)
	 */
	result = result + c;

	std::cout << "operator+ "
	          << ((clockEnd-clockStart)/(double)CLOCKS_PER_SEC/NB_PROFILING_LOOP)
			  << " seconds"
			  << std::endl;

	clockStart = clock();
	for(long i=0; i<NB_PROFILING_LOOP; i++){
		c = a - b;
	}
	clockEnd = clock();

	/* Force code generation by using the result
	 * else optimizer might just remove the previous loop ;)
	 */
	result = result + c;

	std::cout << "operator- "
	          << ((clockEnd-clockStart)/(double)CLOCKS_PER_SEC/NB_PROFILING_LOOP)
			  << " seconds"
			  << std::endl;

	clockStart = clock();
	for(long i=0; i<NB_PROFILING_LOOP; i++){
		c = a * b;
	}
	clockEnd = clock();

	/* Force code generation by using the result
	 * else optimizer might just remove the previous loop ;)
	 */
	result = result + c;

	std::cout << "operator* "
	          << ((clockEnd-clockStart)/(double)CLOCKS_PER_SEC/NB_PROFILING_LOOP)
			  << " seconds"
			  << std::endl;

	clockStart = clock();
	for(long i=0; i<NB_PROFILING_LOOP; i++){
		c = a / b;
	}
	clockEnd = clock();

	/* Force code generation by using the result
	 * else optimizer might just remove the previous loop ;)
	 */
	result = result + c;

	std::cout << "operator/ "
	          << ((clockEnd-clockStart)/(double)CLOCKS_PER_SEC/NB_PROFILING_LOOP)
			  << " seconds"
			  << std::endl;

	/* Display the result to avoid optimizer removing the computations */
	std::cout << "result= " << result << std::endl;

	return EXIT_SUCCESS;
}

